﻿using System.Windows.Forms;
using HighDiveEngine.Aggregates;
using HighDiveEngine.Model;
using HighDiveJudge.Interfaces;
using HighDiveJudge.Resources;

namespace HighDiveJudge
{

    public class JudgeAppPresenter
    {
        #region Properties

        private IJudgeApp _app;
        private IJudgeAppForm _form;

        private delegate void DelegateViewShowView(FormViews view);
        private delegate void DelegateViewUpdateShownDives(Dive dive, DiveList diveHistory);


        #endregion

        #region Constructor

        public JudgeAppPresenter(JudgeApp app, IJudgeAppForm form)
        {
            _app = app;
            _form = form;

            _form.EventLogin += _login;
            _form.EventLogout += _logout;
            _form.EventSendScore += _updateScore;
            _app.EventContestEnded += _contestEnded;
            _app.EventLoginSuccessful += _loginSuccessful;
            _app.EventLoginRefused += _loginRefused;
            _app.EventConnectionFailed += _connectionFailed;
            _app.EventUpdateFromAdminProgram += _updateShownDives;
        }

        private void _contestEnded()
        {
            _form.Invoke(new MethodInvoker(_form.ContestEnded));
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Attempts to connect to the admin application to verify the provided idString
        /// </summary>
        /// <param name="idString">The judge's unique Id String</param>
        /// <param name="ipAdress">The admin computer's IP-adress</param>
        /// <param name="listenPort">The admin computer's port number</param>
        private void _login(string idString, string ipAdress, int listenPort)
        {
            _app.Login(idString, ipAdress, listenPort);            
        }


        /// <summary>
        /// Logs out and disconnects from the admin computer
        /// </summary>
        private void _logout()
        {
            _app.Logout();
            _form.Invoke(new DelegateViewShowView(_form.ShowView), FormViews.LoggedOut);
        }

        /// <summary>
        /// Tells the form that a login has been successful and resets the dives in the admin app
        /// </summary>
        private void _loginSuccessful()
        {
            if (_app.Connected)
            {
                _form.Invoke(new DelegateViewShowView(_form.ShowView), FormViews.LoggedIn);
                _updateShownDives();
            }
        }

        /// <summary>
        /// Passes on to the form that a connection has been refused
        /// </summary>
        private void _loginRefused()
        {
            _form.Invoke(new MethodInvoker(_form.LoginRefused));
        }

        /// <summary>
        /// Called when a connection fails.
        /// </summary>
        private void _connectionFailed()
        {
            _form.Invoke(new MethodInvoker(_form.ConnectionFailed));
        }

        /// <summary>
        /// Updates the score of the specified Dive
        /// </summary>
        private void _updateScore(Dive dive, double score)
        {
            _app.UpdateScore(dive, score);
            if (dive == _app.CurrentDive)
            {
                _app.UpdateDiveHistory();

            }
            _updateShownDives();
        }

        /// <summary>
        /// Updates the dives shown in the GUI
        /// </summary>
        private void _updateShownDives()
        {
            _form.Invoke(new DelegateViewUpdateShownDives(_form.UpdateShownDives), _app.CurrentDive, _app.DiveHistory);
        }

        #endregion
    }
}
